home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.004
/
FGUSER15.TXT
< prev
next >
Wrap
Text File
|
1995-05-29
|
24KB
|
602 lines
Using the Editor
"An ass loaded with gold climbs to
the top of the castle"
English Proverb
Introduction
One of the most requested tools over the past few years has
been a plug-in editor which you can easily incorporate into an
application. Well here it is. Rather than implement a basic little
line editor, we decide to endow Gold with a beefy "Arnold" editor
that includes the following features:
Automatic dynamic word wrap
Clipboard support allowing for cut/copy and paste
Full mouse support
Support for optional headers and footers
Hooks to allow customization
Figure 15.1
Edit Windows
Basic Principles
Many of the principles used with the editing functions are
identical with those used for listing and browsing data (discussed
in the last chapter).
Gold needs to know the main properties of the data and the
characteristics of the window in which the data will be displayed.
For example, before an edit window can be displayed, Gold needs to
know some of the following information:
What type of data is to be displayed, e.g. a single linked
list, double linked list, array, etc.
Where the data is stored, i.e. the name of the variable.
The dimensions and style of the window.
The window title.
Any optional memo headers and footers.
What colors are to be used.
You define all these memo characteristics by creating a
variable (of type MemoCfg, for memo configuration), initializing
the variable, and then setting various components of the variable
to define your specific needs.
In other words, to display a memo in a window you need at
least two variables: a list configuration variable, and a variable
used to store the data.
Having configured the MemoCfg variable and loaded the data the
following function can be used to provide an edit window:
RunMemo(var MemoDetails: MemoCfg; Tit:StrScreen);
Displays the data identified in MemoDetails in an edit window.
Defining the Memo Configuration
The key to displaying a memo window is to declare a variable
of type MemoCfg, and then call Gold functions to set MemoCfg to
meet your specific needs.
Initializing MemoCfg
Always, always, always call InitMemoCfg to initialize the
MemoCfg variable before calling the other memo procedures and
functions.
InitMemoCfg(var MemoDetails: MemoCfg);
Initializes a memo configuration variable.
Assigning the Data Source
Having initialized the MemoCfg variable you then need to
update the variable with information about the memo data source.
Gold can display the contents of a SingleLL, DoubleLL, or a string
array. Dependent upon your data source, you would call one of the
following procedures to update the MemoCfg variable with the data
source details:
MemoAssignSLL(var MemoDetails: MemoCfg; var MemoSource: SingleLL);
Sets the MemoCfg variable data source as a single linked list
stored in the variable MemoSource.
MemoAssignDLL(var MemoDetails: MemoCfg; var MemoSource: DoubleLL);
Sets the MemoCfg variable data source as a double linked list
stored in the variable MemoSource.
MemoAssignArray(var MemoDetails: MemoCfg; var MemoSource;
StrLen:Byte;ArrayElements:byte);
Sets the MemoCfg variable data source as a string array stored
in the variable MemoSource. The last two parameters define the
length of each string in the array, and the number of elements in
the array, respectively.
Setting Window Properties
When the MemoCfg variable is initialized, the window
properties (such as the window position and dimensions) are set to
some standard defaults. If these defaults are not appropriate, you
can customize them with the following two procedures
MemoSetWin(var MemoDetails: MemoCfg; X1,Y1,X2,Y2:integer;
Style:byte);
Defines the upper left and lower right corners of the window
along with the window style. (Refer to chapter 4 for a discussion
of window styles.)
MemoSetGaps(var MemoDetails: MemoCfg;
LeftGap,RightGap,BotGap,TopGap: byte);
This procedure allows you to set the gap or whitespace area
around the memo body. The editable data does not need to fill the
entire window.
If you want to change the window defaults, update the
following variables: MemoVars.X1, MemoVars.Y1, MemoVars.X2,
MemoVars.Y2, and MemoVars.WiStyle.
Setting the Window Colors
As usual, the default colors are defined in the TINT
structure, and the following elements pertain to memo windows:
MemoHi,
MemoNorm,
MemoBlock,
MemoScrollbarHi,
MemoScrollbarNorm,
MemoBorder1,
MemoBorder2,
MemoBorderOff,
MemoTitle,
MemoHeaders,
MemoIcons,
You can modify the defaults (used by any new memo windows
initialized after the modification) by using the standard
GoldSetColor procedure.
You can modify the colors of a specific memo window by using
the following function:
MemoSetColor(var MemoDetails: MemoCfg; A:TintElement;C:byte);
Sets the color of one of the elements of a memo window.
The following code is an extract from DEMMEM6.PAS which
customizes the list display colors:
procedure CustomizeColors;
{}
begin
MemoSetColor(MemoSettings,MemoHi,
LightGrayonMagenta);
MemoSetColor(MemoSettings,MemoBlock,YellowOnBlue);
MemoSetColor(MemoSettings,MemoNorm,YellowOnMagenta);
MemoSetColor(MemoSettings,MemoScrollbarHi,
WhiteOnMagenta);
MemoSetColor(MemoSettings,MemoScrollbarNorm,
WhiteOnMagenta);
MemoSetColor(MemoSettings,MemoBorder1,
YellowOnMagenta);
MemoSetColor(MemoSettings,MemoBorder2,
YellowOnMagenta);
MemoSetColor(MemoSettings,MemoBorderOff,
BlackOnMagenta);
MemoSetColor(MemoSettings,MemoTitle,WhiteOnMagenta);
MemoSetColor(MemoSettings,MemoHeaders,
GreenOnMagenta);
MemoSetColor(MemoSettings,MemoIcons,
LightCyanOnMagenta);
end; { CustomizeColors }
Using Headers and Footers
Memo windows support multi-line headers and footers. Out of
the box, Gold limits the number of heading lines and footer lines
to 4, but you can change the number by assigning a different value
to the constants ListMaxHeaders and ListMaxFooters declared in
GOLDLIST.
To minimize memory usage, all headers and footers must be
stored as string variables in your program. (Gold simply stores a
pointer to the variable.)
The following six procedures can be used to manage the headers
and footers:
MemoAssignHeader(var MemoDetails: MemoCfg; Line:byte; var
Heading:string);
Sets the memo configuration variable to display a string as a
header. A string variable must be passed -- a string literal will
not be accepted. The line must be a value in the range 1 to
ListMaxHeaders (which defaults to 4).
MemoAssignFooter(var MemoDetails: MemoCfg; Line:byte; var
Footnote:string);
Sets the memo configuration variable to display a string as a
footer. A string variable must be passed -- a string literal will
not be accepted. The line must be a value in the range 1 to
ListMaxFooters (which defaults to 4).
MemoRemoveHeader(var MemoDetails: MemoCfg; Line:byte);
Removes a header line which was previously assigned with
MemoAssignHeader.
MemoRemoveFooter(var MemoDetails: MemoCfg; Line:byte);
Removes a header line which was previously assigned with
MemoAssignFooter.
MemoScrollHeader(var MemoDetails: MemoCfg; On:boolean);
Pass TRUE if the headings should be scrolled right and left
when the user scrolls the memo body right and left, or FALSE if the
header should remain fixed.
MemoScrollFooter(var MemoDetails: MemoCfg; On:boolean);
Pass TRUE if the headings should be scrolled right and left
when the user scrolls the memo body right and left, or FALSE if the
header should remain fixed
You can automatically center a header or footer by prefixing
the string with the ^ character.
Refer to the demo file DEMMEM1.PAS for an example of a memo
with a heading.
Controlling Word Wrap
IMPORTANT NOTE: The GOLDFLAG.INC file includes a conditional
compiler directive named WORDWRAP. This compiler directive must be
enabled (i.e. there should be no spaces either side of the $ symbol
in the {$DEFINE statement) if your program is to support word
wrapping.
Gold can be configured to edit with or without automatic word
wrapping. When word wrapping is disabled, the editor functions like
a normal text editor, e.g. just like DOS' EDIT program. By default,
word wrapping is enabled, but the following procedure controls the
word wrapping state:
MemoSetWordWrap(var MemoDetails: MemoCfg; On:boolean);
Pass TRUE to enable word wrapping and FALSE to disable it.
Gold word wraps all text in the current paragraph. You
indicate the end of a paragraph by inserting an end of paragraph
character in the text stream. This character is defined in the
GOLDMEMO unit by the variable MemoVars.EndofParaCode. The code will
default to char(20) and is displayed as "". This same code will be
inserted into the text during an edit session when the user presses
the Enter key.
Before the text is initially displayed at the beginning of a
RunMemo session, Gold will automatically wrap the text. It is very
important that the source text includes embedded end of paragraph
codes where appropriate. Otherwise, Gold will assume the entire
stream is one big happy paragraph!
Listed below is an extract from DEMMEM1.PAS which shows the
text stream being created. Notice the embedded end of paragraph
codes inserted at strategic places in the text.:
procedure BuildSLL;
{}
var I: integer;
begin
InitSLLStr(TextData);
I := 0;
SLLSetActiveList(TextData);
inc(I,SLLAddStr('Turbo Pascal with Objects ...'));
inc(I,SLLAddStr('programming system for DOS...'));
inc(I,SLLAddStr('development.Features DOS...'));
inc(I,SLLAddStr('application frameworks; wo...' ));
inc(I,SLLAddStr('create DOS, Windows Dynamic ...'));
inc(I,SLLAddStr('across platforms.Better ...'));
inc(I,SLLAddStr('with the award-winning Tech....'));
if I <> 0 then
begin
PromptOK(' ERROR ','Not enough memory !');
halt;
end;
end; {BuildSLL}
If you want to display an empty window with no initial text,
you must (as a minimum) assign one end of paragraph marker to the
text stream -- this is similar to many word processors where a new
document always contains an end of document symbol.
The following code is an extract from DEMMEM2.PAS which
attempts to load the source text from a file. If the file load
fails, a single end of paragraph marker is assigned to the text:
procedure BuildSLL;
{}
begin
InitSLLStr(TextData);
SLLSetActiveList(TextData);
if SLLLoadFromFile(TextFileName) <> 0 then {bad}
if SLLAddStr(MemoVars.EndofParaCode) <> 0 then
begin
PromptOK(' ERROR ','Not enough memory');
halt;
end;
end; {BuildSLL}
Using the Clipboard
That's right, Gold edit session support an internal clipboard
enabling cut and paste operations!
IMPORTANT NOTE: The GOLDFLAG.INC file includes a conditional
compiler directive named CUTANDPASTE. This compiler directive must
be enabled (i.e. there should be no spaces either side of the $
symbol in the {$DEFINE statement) if your program is to support cut
and paste.
Having said that there is support for cut and paste, there is
not a lot left to say. Gold is initially configured to support
standard key operations like Shift-Del and Ctrl-Ins. These cut and
paste keystrokes are defined in the MemoVars global variable, and
you may modify them to support custom keystrokes for copy and paste
operations. List below is an extract from the initialization
procedure which defines these keystrokes:
procedure MemoDefaultSettings;
{}
begin
with MemoVars do
begin
DeltoScrapKey := 263; {Shift-Del}
DelBlockKey := 339; {Del}
CopyToScrapkey := 260; {Ctrl-Ins}
InsfromScrapKey := 261; {Shift-Ins}
MarkBlockStartKey := 321; {F7}
MarkBlockEndKey := 322; {F8}
HideBlockKey := 2; {Ctrl-B}
end;
end;
Customizing General Edit Keystrokes
In the last section you learned how to customize the
keystrokes related to the cut and paste operations. List below are
some other keystrokes which are defined in the global variable
MemoVars. You may assign new values to any of these keystrokes.
procedure MemoDefaultSettings;
{}
begin
with MemoVars do
begin
WordRightKey := 372; {Ctrl-Right}
WordLeftKey := 371; {Ctrl-Left}
TopOfWindowKey := 375; {Ctrl-Home}
BotOfWindowKey := 373; {Ctrl-End}
TopofMemoKey := 388; {Ctrl-PgUp}
BotofMemoKey := 374; {Ctrl-PgDn}
EndEditKey := 324; {F10}
EscEditKey := 27; {Esc}
end;
end;
Determining the Dirty State
Each MemoCfg variable keeps track of whether the data has been
edited. When the variable is initialized (using InitMemoCfg) the
state is set to FALSE, i.e. the memo has not been edited. Gold will
automatically set the dirty flag to true if the data is edited in
any way.
The following two procedures can be used to get and set the
state of the dirty flag:
MemoIsDirty(var MemoDetails: MemoCfg):boolean;
Returns TRUE if the memo has been edited.
MemoSetDirty(var MemoDetails: MemoCfg; On:boolean);
Sets the dirty flag which indicates whether or not the data
has been edited.
The demo files DEMMEM2.PAS and DEMMEM5.PAS use these functions
during file save operations.
Using Memo Hooks
Gold provides two different hooks for customizing memo
windows: the character hook and the hind hook.
The Character Hook
A character hook is a procedure which is called every time a
key is pressed or a mouse button is clicked while a memo window has
focus. The hooked procedure is called before the key is processed
by Gold. The hook is particularly useful for trapping special keys
like F1 for help, or Ctrl-Y to delete a file, for example.
All you have to do is create a procedure following some
specific rules, and then call the MemoAssignCharHook procedure to
instruct Gold to call your procedure every time a key is pressed.
For a procedure to be eligible as a character hook it must
adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in Chapter 3
for further information.
The procedure must be declared with four parameters. The first
parameter is of type MemoCfgPtr, followed by one variable
parameter of type word and two variable parameters of type
byte. These parameters identify the MemoCfg variable used to
display the memo along with the user input, i.e. the Key, X
and Y.
The following procedure declaration follows these rules:
{$F+}
procedure MyCharHook(MP: MemoCfgPtr; var Code:word;var
X,Y:byte);
begin
{some code}
end; {MyCharHook}
{$F-}
The following procedure is then called to instruct Gold to
call your procedure after each input:
MemoAssignCharHook(var MemoDetails: MemoCfg; Proc:MemoCharHook);
Instructs Gold to call the specified procedure before
processing each user input to a memo window.
If, subsequently, you want to remove the character hook,
execute the following procedure:
MemoRemoveCharHook(var MemoDetails: MemoCfg);
Removes a list character which was previously assigned with
MemoAssignCharHook.
The demo file DEMMEM7.PAS illustrates a character hook
providing Ctrl-Y line deletion support.
The Hind Hook
A memo hook is similar to a character hook, except the hook is
called after an input has been processed by Gold. If you want to
write some additional information to the screen based on the
cursor, you should take advantage of the hind hook.
For a procedure to be eligible as a hind hook it must adhere
to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in Chapter 3
for further information.
The procedure must be declared with one parameter of type
MemoCfgPtr.
The following procedure declaration follows these rules:
{$F+}
procedure MyHineyHook(MemoDetailsPtr:MemoCfgPtr);
begin
{some code}
end; {MyHineyHook}
{$F-}
The following procedure is then called to instruct Gold to
call your procedure after each input:
MemoAssignHindHook(var MemoDetails: MemoCfg; Proc:MemoHindHook));
Instructs Gold to call the specified procedure after
processing each user input to a list window, and once when the
window is first displayed.
The variable parameter which is passed to the procedure is
actually a pointer to the MemoCfg variable which is being used by
the memo. You can de-reference the pointer to access the variable,
for example:
Total := MemoDetails^.TotalNodes
If, subsequently, you want to remove the hind hook, execute
the following procedure:
MemoRemoveHindHook(var MemoDetails:MemoCfg);
Removes a memo hind which was previously assigned with
MemoAssignHindHook.
The demo file DEMMEM8.PAS shows a hind hook used to displayed
the cursor position, and indicates when the file has been modified.
Launching Memos on the Desktop
The desktop equivalent of RunMemo, is LaunchMemo which is
described as follows:
LaunchMemo(var MemoDetails: MemoCfg;Tit:StrScreen;
CloseProc:MemoCloseProc): byte;
Adds a memo window to the desktop. The function returns the
number (or handle) of the newly created window.
Like its Run counter part, the LaunchMemo function is passed a
MemoCfg variable and a title. Additionally, LaunchMemo is passed a
close function as a third parameter. This close function is called
whenever the user tries to close the window on the desktop, and it
provides you with an opportunity to do any housekeeping (such as
disposing of linked lists) before the window is closed.
For a function to be eligible as a memo close hook it must
adhere to the following rules:
The function must be declared as a far function at the root
level. Refer to the section Understanding Hooks in Chapter 4
for further information.
The function must be declared with one parameter of type
MemoCfgPtr, and one integer. The function must return a
boolean value.
The following procedure declaration follows these rules:
{$F+}
function GoodbyeList(var MCP: MemoCfgPtr; Handle:integer):
boolean;
{}
begin
PopUpSetActive(ListMenu,201,true);
SLLDestroy;
GoodbyeList := true;
end; { GoodbyeList }
{$F-}
If the function returns false, the window will not close. The
first parameter passed to the function is a pointer to the MemoCfg
variable used to display the list. You can de-reference this
pointer to access the variable, for example:
Total := MemoDetails^.ActiveNode
The demo file DEMMEM5.PAS shows the LaunchMemo function in all
its glory.
Saving Files in Hooks or on the Desktop
IMPORTANT NOTE: Behind the scenes, a copy of the line
containing the cursor is maintained by Gold. As edits are made to
the memo, Gold simply updates the single line copy -- this offers
improved performance. When the user moves lines, the copy is posted
back to the original data and a copy of the new line is made. "Why
do I care" I hear you ask. Read On
If you plan to save the memo in a hook, or as part of the
close function, you must instruct Gold to update the original data
with the current line using the following function:
MemoStoreActiveLine(var MemoDetails: MemoCfg);
Instructs Gold to write back (to the original data source) all
the edits performed on the active line, i.e. the line containing
the cursor.
This procedure is used in DEMMEM5.PAS.
Error Handling
The RunMemo function has the potential to fail. For example,
there may be insufficient memory to create the window. After
calling RunMemo , always call the function, LastMemoError to see if
the operation was successful.
If LaunchMemo returns a zero, the window was not created.